
#include "Vm.h"
#include "include.h"

int VM_FunSel = 0;
int VM_CodeSegmentFraction = -2;


int VmISAPos = -1;
VTS32FXISA CodeStack[VMSTACKSIZE] = { 0 };
FunPointer funPtr;

int VmIndexInc(int Bias) {
	VmISAPos += Bias;
	return VmISAPos;
}

int VmIndex(void)
{
	return VmISAPos;
}

int VmNext(void)
{
	if (VmISAPos >= VMSTACKSIZE || VmISAPos < 0)
	{
		return VMSMT_STACKOVERFLOW;
	}
	unsigned char Cmd = CodeStack[0].code >> 2, CodeOver = 0;
	switch (Cmd)
	{
	case VM_NOP:
	{
		char DelayTimes = CodeStack[1].code;
		if (DelayTimes > 0)
		{
			DelayTimes--;
			VmISAPos--;
		}
		else {

			VmISAPos = -1;
			CodeOver = true;
		}

		CodeStack[1].code = DelayTimes;
	}
	break;
	case VM_SETGPIO:
		if (nullptr != funPtr.setGPIO)
		{
			int GPIOSel = CodeStack[0].code & 0x3;
			short Pin = (CodeStack[1].code << 16) | (CodeStack[2].code);
			funPtr.setGPIO(GPIOSel, Pin);
		}
		CodeOver = true;

		break;
	case VM_RESETGPIO:
		if (nullptr != funPtr.resetGPIO)
		{
			int GPIOSel = CodeStack[0].code & 0x3;
			short Pin = (CodeStack[1].code << 16) | (CodeStack[2].code);
			funPtr.resetGPIO(GPIOSel, Pin);
		}
		CodeOver = true;
		break;
	case VM_DISPLAY: {

		static int VDIO = (1 << 3);
		static int VCLK = (1 << 4);
		static int VSTB = (1 << 5);
		static char vgpiodio = GPIOA_PORT;
		static char vgpioclk = GPIOA_PORT;
		static char vgpiostb = GPIOA_PORT;
		static char data, NoCode;
		if (VmISAPos == 0) {
			VDIO = 1 << (CodeStack[1].code & 0x3F);
			VCLK = 1 << (CodeStack[2].code & 0x3F);
			VSTB = 1 << (CodeStack[3].code & 0x3F);
			vgpiodio = CodeStack[1].code>>6;
			vgpioclk = CodeStack[2].code>>6;
			vgpiostb = CodeStack[3].code>>6;
			
			VmIndexInc(3);
			VmISAPos = 3;
			NoCode = 0;
		}
		else {
			data = CodeStack[VmISAPos].code;
			if (NoCode >= 1) {
				CodeOver = true;
				VmISAPos = -1;
			}
			else if ((1 << 7) & data) {
				//nop操作,需要位移两次
				data &= ~(1 << 7);
				char delay_times = (0x7F & data);
				if (delay_times > 0) {
#ifdef MYDEBUG 
					printf_s("sleep %d ",delay_times);
				//	std::cout << "sleep " << delay_times << std::endl;
#endif
					delay_times--;
				}
				CodeStack[VmISAPos].code = (delay_times | (1 << 7));
				NoCode = 0;
				VmIndexInc(1);
			}
			else if (((1 << 6)) & data && NoCode < 2) {
				CodeOver = true;
				VmISAPos = -1;;
				NoCode++;
			}
			else {
				
				short set = 0, reset = 0;
				if ((1 << 0) & data) {
					set |= VDIO;
				}
				else {
					reset |= VDIO;
				}

				if ((1 << 1) & data) {
					set |= VCLK;
				}
				else {
					reset |= VCLK;
				}

				if ((1<<2) & data) {
					set |= VSTB;
				}
				else {
					reset |= VSTB;
				}
				if (nullptr != funPtr.resetGPIO && reset) {
					funPtr.resetGPIO(GPIOA_PORT, reset);
				}
				if (nullptr != funPtr.setGPIO && set) {
					funPtr.setGPIO(GPIOA_PORT, set);
				}

				NoCode = 0;
			}
		}
	}
				   break;
	default:
		break;
	}

	if (!CodeOver) { VmIndexInc(1); }
	else { VmISAPos = -1; }
	if (-1 == VmISAPos) return VMSMT_END;
	return VM_END;
}

void VmSetCode(VTS32FXISA* tc)
{


}

int VmResetISAPos(void)
{
	VmISAPos = -1;
	if (nullptr != CodeStack) {
		if ((CodeStack[0].code >> 2) != VM_END) {
			VmISAPos = 0;
		}
	}
	return 0;
}

int VmCmdPos(void)
{
	return VmISAPos;
}


